﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.IO;
using Microsoft.VisualStudio.TestTools.Vsip;
using System.Linq;
using System.Collections.Generic;
using System.Collections;
using TLM.VsmdiReader;

namespace TLM.TestCategoryGenerator.Test
{
    [TestClass]
    public class GeneratorTest
    {
        const string ID_CONCAT = "TestID";
        string _testListsPath;
        string _testResultPath;
        ITestManagement _testManagementStub;

        [TestInitialize]
        public void InitializeVariables()
        {
            string assemblyLocation = System.Reflection.Assembly.GetExecutingAssembly().Location;
            _testListsPath = System.IO.Path.GetDirectoryName(assemblyLocation);

            // The generator uses the TestManagement and TMI to get the FQN of a test by it's Id.
            // Since we can't easily get a real TMI up and running we have to create a stub.
            // This also makes sure we have full control of the return values of the mocks.
            _testManagementStub = new Microsoft.VisualStudio.TestTools.Vsip.Fakes.StubITestManagement()
            {
                TmiInstanceGet = () =>
                {
                    return new Microsoft.VisualStudio.TestTools.Common.Fakes.StubITmi()
                    {
                        GetTestTestId = (testId) => 
                        { 
                            return new Microsoft.VisualStudio.TestTools.Common.Fakes.StubITestElement() 
                            { 
                                HumanReadableIdGet = () => 
                                { 
                                    return ID_CONCAT + testId.Id.ToString(); 
                                } 
                            }; 
                        }
                    };
                }
            };

            // The generator expects a path where it can save all the playlists
            string resultPath = Path.Combine(_testListsPath, @"GeneratorTestResults\");

            // If the directory already exists it has to be deleted (this can happen when the test is interrupted)
            if (Directory.Exists(resultPath))
            {
                Directory.Delete(resultPath, true);
            }

            _testResultPath = Directory.CreateDirectory(resultPath).FullName;
        }
        
        /// <summary>
        /// Traverses the vsmdi file to retreive all test links
        /// </summary>
        /// <param name="file">the VSMDI file</param>
        /// <returns>the Test Lists</returns>
        private IEnumerable<TestLink> AllTestLinks(VsmdiFile file) 
        {
            Stack<TestList> todo = new Stack<TestList>();
            todo.Push(file.ListOfTests);
            while (todo.Count != 0)
            {
                var item = todo.Pop();
                foreach (var link in item.TestLinks)
                {
                    yield return link;
                }
                foreach (var list in item.ChildLists)
                {
                    todo.Push(list);
                }
            }
        }

        private TestList CreateTestTestList(int fanWidth, int depth)
        {
            TestList list = new TestList()
            {
                TestLinks = Enumerable.Repeat(new TestLink()
                {
                    Id = Guid.NewGuid(),
                    Name = Guid.NewGuid().ToString(),
                    Enabled = true,
                }, fanWidth).ToArray(),
                Id = Guid.NewGuid(),
                Name = Guid.NewGuid().ToString(),
                Enabled = true
            };

            if (depth > 0)
            {
                list.ChildLists = Enumerable.Repeat(CreateTestTestList(fanWidth, depth - 1)
                    , fanWidth).ToArray();
            }
            return list;
        }

        [TestCleanup]
        public void CleanupFolders()
        {
            // We have to cleanup the result folder after the test is completed
            Directory.Delete(_testResultPath, true);
        }
    }
}
